<?php
ArrowController::importModel("templatesSystem.templates.ArrowTemplatesStructure");
ArrowController::importModel("templatesSystem.templates.ArrowTemplateBlock");
ArrowController::importModel("smarty.SmartyCompiler");


/**
 * View control
 * 
 * @version 1.0
 * @license  GNU GPL
 * @author Artur Kmera <artur.kmera@arrowplatform.org> 
 */
abstract class ArrowView {
	
	/**
	 * Arrow template system
	 * 
	 * @var Smarty
	 */
	public $ts;
	
	private $tmpCacheFilePath;
	
	/**
	 * 
	 * @var ArrowTemplateDescriptor
	 */
	protected $templateDescriptor = null;
	
	private static $globals = array();
	
	
	private static $templatesStack = array();
	
	private  $controlsRoot;
	
	public function setControlsRoot( ArrowNode $root ){
		$this->controlsRoot = $root;
	}
	/**
	 * Returns controls root
	 * @return ArrowTagContainer
	 */
	public function getControlsRoot(){
		return $this->controlsRoot;
	}
	
	
	/**
	 * Returns current processed view
	 * @return ArrowView
	 */
	public static function getCurrentView(){
		return end( self::$templatesStack );
	}
	
	public static function getTemplatesStact(){
		return self::$templatesStack;
	}
	
	
	/**
	 * Returns parrent view if exits or null
	 * 
	 * @return ArrowView
	 */
	public static function getParentView(){
		if( isset( self::$templatesStack[count(self::$templatesStack) - 2] ) )
			return self::$templatesStack[count(self::$templatesStack) - 2];
			
		return null;
	}
	
	/**
	 * Register global template var ( {$arrow.global.} )
	 * @param unknown_type $name
	 * @param unknown_type $var
	 */
	public static function addGlobalVar( $name, $var ){
		self::$globals[$name] = $var;
	}
	
	/**
	 * Get global template var ( {$arrow.global.} )
	 * @param unknown_type $name
	 * @param unknown_type $var
	 */	
	public static function getGlobalVar( $name ){
    if(!isset(self::$globals[$name])) return false;
		return self::$globals[$name];
	}		
	
	public function getTemplateDescriptor(){
		return $this->templateDescriptor;
	}
	
	/*
	 * Returns View Template system
	 * 
	 * @return
	 */
	public function getTemplateSystem(){
		return $this->ts;
	}

	
	abstract public function createView(); 
	
	/**
	 * Constructor initialize template system
	 * 
	 * 	 * //TODO jakos zapewnic dostarczenie routera i auth handlera coby sie tak chamsko nie ladowaly
	 */
	public function __construct( ArrowTemplateDescriptor $templateDescriptor ){
		/* Check whether this template can be accessed by user*/ 
		$controller = ArrowController::getDefault();
		$controller->getAccessHandler()->isTemplateAccessible( $templateDescriptor, "show" ) ;
		
		$parentView = $this->getCurrentView();
		//umieszczenie dziecka na stosie widokĂłw
		self::$templatesStack[] = $this;
		
		$this->templateDescriptor = $templateDescriptor;
		$container = $templateDescriptor->getContainer();
		$forceCompile = $container->getforceCompile();
		
		
		$this->ts = new Smarty();
		$this->ts->template_dir = ARROW_CACHE_PATH."/templates/src/";
		$this->ts->compile_dir = ARROW_CACHE_PATH."/templates/compiled/";
		$this->ts->cache_dir = ARROW_CACHE_PATH."/templates/cache/";
		
		//$this->ts->force_compile = $container->getforceCompile();
		//$this->ts->compile_check = $forceCompile;
		$this->ts->caching = $container->getcaching();
		$this->ts->cache_lifetime = $container->getcachingTime();
		if(SUPER_CACHE){
			$this->ts->force_compile = false;
			$this->ts->compile_check = false;
		}
		
		
		$arrowTemplateVars = array( "request" => ArrowRequestContext::getDefault(),
								"pageInput" => ArrowView::getPageInput(),
								"authHandler" => $controller->getAuthHandler(),
								"currentPage" => $this,
								"projectRoot" => "./projects".str_replace( ARROW_PROJECTS_PATH , "",ArrowProject::PATH ),
								"parent" => null,
								"parentVars" => array(),
								"global" => self::$globals
								);
		
											
		if( !empty( $parentView ) ){
			$arrowTemplateVars["parent"] = $parentView;
			$arrowTemplateVars["parentVars"] = $parentView->getTemplateSystem()->_tpl_vars;
		}
		
		
		
		$this->ts->assign("arrow", $arrowTemplateVars);
		
		//WywoĹ‚anie szablonu
		ArrowLogger::log("[ArrowView] Processing template");
		if( $this->templateDescriptor == null ){
			$router = ArrowRouter::getDefault();
			$this->templateDescriptor = $router->getTemplate();
			ArrowLogger::log("[ArrowView] Processing template call: ".$this->templateDescriptor);
		}else{
			ArrowLogger::log("[ArrowView] Processing template display: ".$this->templateDescriptor);			
		}
		
		
		ArrowLogger::log( "[ArrowView] Starting Smarty template system ..." );
		$this->tmpCacheFilePath = $this->templateDescriptor->getFile( $forceCompile );
		
	}
	
	protected  function isCached(){
		return $this->ts->is_cached($this->templateDescriptor->getFile(false));
	}
	
	public function controlsInit(){
		require_once($this->templateDescriptor->getInitInstuctions());
	}
	
	public function afterControlsInit(){}
	
	public function display(){
		
		require_once($this->templateDescriptor->getInitInstuctions());
		
		ArrowLogger::log( "[ArrowView] Displaing template ..." );
		try{
			$completed = $this->ts->fetch($this->tmpCacheFilePath);
			
		}catch (Exception $ex){
			ExceptionHandler::getDefault()->displayException($ex);
			//print $ex->getMessage();
			exit();
		}
		array_pop(self::$templatesStack);
		return $completed;
	}
	
	public function generateControll(){
		require_once($this->templateDescriptor->getInitInstuctions());
		ArrowLogger::log( "[ArrowView] Generating controll ..." );
		$rq = ArrowRequestContext::getDefault();
		$node = $this->getControlsRoot()->getById($rq[ArrowNode::CTRL_NAMESPACE."-ctrlId"]);
		$str = "";
		if( $node instanceof ArrowTag ){
			$str.= $node->generateOutput();
			if($ajax = $node->getParent("ArrowCtrlAjax")){
				$state = ArrowCtrlAjax::generateAjaxStatements($ajax->getId(), $node);
				$str.=$state["state"];
			}
		}elseif( $node instanceof ArrowTagContainer ){
			if($node->isContentCodeKept() && $node->isDisplayed()){
				/*$parser = ArrowTemplateParser::getDefault();
				$parser->parseString($node->getContentCode(), $node);
				$code = $parser->getParsedCode();*/
				
				$compiler = new SmartyCompiler($node->getContentCode(), $this->ts);
				$str.= $node->generateBlockStart().$compiler->getResult().$node->generateBlockEnd();
				if($ajax = $node->getParent("ArrowCtrlAjax")){
					$state = ArrowCtrlAjax::generateAjaxStatements($ajax->getId(), $node);
					$str.=$state["state"];
				}
			}else{
				$str.= $node->generateBlockStart().$node->generateBlockEnd();
				if($ajax = $node->getParent("ArrowCtrlAjax")){
					$state = ArrowCtrlAjax::generateAjaxStatements($ajax->getId(), $node);
					$str.=$state["state"];
				}
			}
		}else
			throw new ArrowCoreException( array("msg" => "Ctrl doesn't exists", "ctrlId" => $rq[ ArrowNode::CTRL_NAMESPACE."-ctrlId"]  ) );
		return $str;
	}
	
	public function runControllAction(){
		require_once($this->templateDescriptor->getInitInstuctions());
		ArrowLogger::log( "[ArrowView] Running controll action..." );
		$rq = ArrowRequestContext::getDefault();
		$node = $this->getControlsRoot()->getById($rq[ArrowNode::CTRL_NAMESPACE."-ctrlId"]);
		$action = $rq[ArrowNode::CTRL_NAMESPACE."-actionDelegate"];
		$data = $rq->getPost();
		return $node->runActionDelegate($action, $data);
	}

	
	/**
	 * Sets page (template) input
	 *
	 * @param Array $data
	 */
	public static function setPageInput( $data ){
		$_SESSION["_arrow_"]["view"]["pageInput"] = $data;
	}

	/**
	 * Gets page (template) input
	 *
	 * @return Array
	 */
	public static function getPageInput(){
		if(isset($_SESSION["_arrow_"]["view"]["pageInput"])){
			$tmp = $_SESSION["_arrow_"]["view"]["pageInput"];
			return $tmp;
		}
		return array();
	}
	
	public function __destruct(){
		unset($_SESSION["_arrow_"]["view"]["pageInput"]);		
	}
	

}
?>